﻿// ## 2022/09/09 # 铃 # 修复bug ##
// ## 2022/09/04 # 铃 # 为新的内政系统做了适配,把征兵值设为0 ##
// ## 2022/03/29 # 铃 # 为新的人口系统重新做了优化 ##
// ## 2021/10/29 # 江东新风 # 结构体存储调用方式改进 ##
// ## 2021/10/10 # 江东新风 # 治安相关函数也搬运至此 ##
// ## 2021/09/15 # 江东新风 # 更改pk::core[]函数为英文##
// ## 2021/02/16 # 江东新风 # 一般城市征兵倍率无法修改bug ##
// ## 2021/01/24 # 江东新风 # 将内政函数内容全搬运到此处，以便其他cpp调用 ##
// ## 2020/12/12 # 江东新风 # 修正参数类型错误 ##
// ## 2020/09/28 # 氕氘氚 ##

namespace inter
{


	int get_population_revenue(int building_id)
	{
		int population_yield = 0;
		int population = 0;
		float 人口税率基数 = 0.3;
		int spec_id = ch::to_spec_id(building_id);
		if (pk::is_valid_base_id(building_id))
		{
			auto base_t = ch::get_base_p(building_id);
			population = base_t.population + base_t.mil_pop_all;
			population_yield = int(sqrt(population) * 人口税率基数 + 200);
			// if (调试模式) pk::trace(pk::format("{},population：{}，gold population_yield：{}", pk::decode(pk::get_name(city)), population, population_yield));
		}
		else if (ch::is_valid_spec_id(spec_id))
		{
			auto spec_t = ch::get_spec_p(spec_id);
			population = spec_t.population;
			population_yield = int(sqrt(population) * 人口税率基数 + 50);
		}

		return population_yield;
	}

	int get_population_harvest(int building_id)
	{
		int population_yield = 0;
		int population = 0;
		int 人口税率基数 = 6;
		int spec_id = ch::to_spec_id(building_id);
		if (pk::is_valid_base_id(building_id))
		{
			auto base_t = ch::get_base_p(building_id);
			population = base_t.population;
			population_yield = int(sqrt(population) * 人口税率基数 + 3000);
			// if (调试模式) pk::trace(pk::format("{},population：{}，gold population_yield：{}", pk::decode(pk::get_name(city)), population, population_yield));
		}
		// 县城的驻军要额外耗粮,因此保底值值得商榷
		else if (ch::is_valid_spec_id(spec_id))
		{
			auto spec_t = ch::get_spec_p(spec_id);
			population = spec_t.population;
			population_yield = int(sqrt(population) * 人口税率基数 + 1000);
		}

		return population_yield;
	}

	float get_market_efficiency(float population, int basic_yield)
	{
		return basic_yield > 0 ? pk::min(1.1f, pk::max(0.5f, ((population / 10000) / (basic_yield * 0.12f)))) : 1.0f;
	}

	float get_farm_efficiency(float population, int basic_yield)
	{
		return basic_yield > 0 ? pk::min(1.1f, pk::max(0.5f, ((population / 10000) / (basic_yield * 0.006f)))) : 1.0f;
	}

	pk::int_int cal_gold_yield(pk::city @city, bool cal_market = true)
	{

		// 判断有无造币厂
		bool has_造币 = false;
		if (造币谷仓无需相邻 and cal_market)
		{
			for (int i = 0; i < city.max_devs; i++)
			{
				// 为了避免遍历城市周围地格，所以城市信息里会存开发土地的信息，如果想要支城能具有影响收入效果，可以参考这个
				pk::building @t_building = city.dev[i].building;
				if ((pk::is_alive(t_building) && t_building.facility == 시설_조폐 && t_building.completed) or !city.is_player())
				{
					has_造币 = true;
					break;
				}
			}
		}

		// pk::int_int yield = pk::int_int(0,0);
		int basic_yield = 0;
		int market_yield = 0;
		for (int i = 0; i < city.max_devs; i++)
		{
			pk::building @building = city.dev[i].building;
			int facility_id = -1;

			if (pk::is_alive(building))
			{
				facility_id = building.facility;
				switch (facility_id)
				{
					case 设施_市场1级:
					case 设施_大市场:
					case 设施_渔市:
					case 设施_黑市:
						if (!building.completed)
							continue;
						break;
					case 设施_市场2级:
						if (!building.completed)
							facility_id = 设施_市场1级;
						break;
					case 设施_市场3级:
						if (!building.completed)
							facility_id = 设施_市场2级;
						break;
					default:
						continue;
				}
			}
			pk::facility @facility = pk::get_facility(facility_id);

			if (pk::is_alive(facility))
			{
				int y = facility.yield;
				basic_yield += y;
				// 造币加成

				if (cal_market)
				{
					if (facility_id == 设施_市场1级 or facility_id == 设施_市场2级 or facility_id == 设施_市场3级 or (造币对鱼市大市生效 and (facility_id == 设施_大市场 or facility_id == 设施_渔市)))

					{
						if (造币谷仓无需相邻 && has_造币 || func_49ed70(building.get_pos(), 设施_造币))
						{
							// 变法
							if (ch::has_skill(pk::get_building(city.get_id()), 特技_变法))		   // 变法
								y = int(y * pk::core::skill_constant_value(特技_变法, 1) / 100.f); // 改成百分比好了~
							else
								y = int(y * 1.5f);
						}
						// if (city.is_player()) pk::trace(pk::format("{},造币谷仓无需相邻:{},has_造币：{},{},{}", pk::decode(pk::get_name(city)),facility_id == 设施_市场1级, facility_id == 设施_市场2级,facility_id == 设施_市场3级,int(y * 1.5f)));
					}
					market_yield = market_yield + y;
				}
			}
		}
		return pk::int_int(basic_yield, market_yield);
	}

	pk::int_int cal_food_yield(pk::city @city, bool cal_farm = true)
	{

		// 判断有无谷仓
		bool has_谷仓 = false;
		if (cal_farm and 造币谷仓无需相邻)
		{
			for (int i = 0; i < city.max_devs; i++)
			{
				pk::building @t_building = city.dev[i].building;
				// AI特别不喜欢建谷仓,缺粮很严重,不得已,暂时先强制AI拥有谷仓效果.
				if ((pk::is_alive(t_building) && t_building.facility == 设施_谷仓 && t_building.completed) or !city.is_player())
				{
					has_谷仓 = true;
					break;
				}
			}
		}

		int basic_yield = 0;
		int farm_yield = 0;
		for (auto i = 0; i < city.max_devs; i++)
		{
			pk::building @building = city.dev[i].building;
			int facility_id = -1;

			if (pk::is_alive(building))
			{
				facility_id = building.facility;
				switch (facility_id)
				{
					case 设施_农场1级:
					case 设施_军屯农:
						if (!building.completed)
							continue;
						break;
					case 设施_农场2级:
						if (!building.completed)
							facility_id = 设施_农场1级;
						break;
					case 设施_农场3级:
						if (!building.completed)
							facility_id = 设施_农场2级;
						break;
					default:
						continue;
				}
			}

			pk::facility @facility = pk::get_facility(facility_id);
			if (pk::is_alive(facility))
			{
				int y;
				// 军屯计入y参与后续计算,但是军屯不参与基础值的计算,不受到市场效率的影响.
				if (facility_id == 设施_军屯农)
					y = int(float(city.troops) / 军屯农单倍收入人数 * facility.yield);

				else if (facility_id == 设施_农场1级 or facility_id == 设施_农场2级 or facility_id == 设施_农场3级)
				{
					basic_yield += facility.yield;
					y = facility.yield;
				}

				// 军屯农收入计算

				// 谷仓加成
				if (cal_farm)
				{
					if (facility_id == 设施_农场1级 or facility_id == 设施_农场2级 or facility_id == 设施_农场3级 or (谷仓对军屯农生效 and facility_id == 设施_军屯农))
					{
						if (造币谷仓无需相邻 && has_谷仓 || func_49ed70(building.get_pos(), 设施_谷仓))
						{
							if (ch::has_skill(pk::get_building(city.get_id()), 特技_变法)) // 变法
								y = int(y * pk::core::skill_constant_value(特技_变法, 1) / 100.f);
							else
								y = int(y * 1.5f);
						}
					}
					farm_yield = farm_yield + y;
					// pk::trace(pk::format("{},y:{},farm_yield:{}", pk::decode(pk::get_name(city)), y, farm_yield));
				}
			}
		}
		// 1000的保底值挪到for的外面
		farm_yield = farm_yield + 1000;

		return pk::int_int(basic_yield, farm_yield);
	}

	// 内政全局系数
	int incomes_global_impact(int n, pk::building @building, int mode /* 0为金,1为粮草 */)
	{
		int ratio = 100;
		int building_id = building.get_id();
		int spec_id = ch::get_spec_id(building);
		pk::force @force = pk::get_force(building.get_force_id());

		// 难度修正
		switch (pk::get_scenario().difficulty)
		{
			case 难易度_超级:
				if (building.is_player())
					ratio = 90;
				else
					ratio = 110;
				break;
			case 难易度_上级:
				if (building.is_player())
					ratio = 100;
				else
					ratio = 100;
				break;

			case 难易度_初级:
				if (building.is_player())
					ratio = 120;
				else
					ratio = 100;
				break;
		}

		// 全局修正系数
		if (mode == 0)
			ratio = ratio * (building.is_player() ? 玩家金收入倍率 : 电脑金收入倍率) / 100;
		if (mode == 1)
			ratio = ratio * (building.is_player() ? 玩家粮收入倍率 : 电脑粮收入倍率) / 100;

		if (pk::is_alive(force))
		{
			if (pk::has_tech(force, 技巧_木牛流马) and mode == 1 and building_id < 据点_末)
				ratio = ratio * 110 / 100;

			if (pk::has_tech(force, 技巧_木牛流马) and mode == 1 and building_id >= 据点_末)
				ratio = ratio * 120 / 100;

			if (pk::has_tech(force, 技巧_港关扩张) and mode == 0 and building_id < 据点_末)
				ratio = ratio * 110 / 100;

			if (pk::has_tech(force, 技巧_港关扩张) and mode == 0 and building_id >= 据点_末)
				ratio = ratio * 120 / 100;
		}

		int guaranteed_revenue = 0;
		int guaranteed_harvest = 0;
		int guaranteed_revenue_bouns = 0;
		int guaranteed_harvest_bouns = 0;

		if (mode == 0)
		{
			if (building_id < 据点_末)
			{

				if (ch::is_gate(building.get_id()))
					guaranteed_revenue = guaranteed_revenue_bouns / 2;

				else
					guaranteed_revenue = guaranteed_revenue_bouns;
			}
			else if (ch::is_valid_spec_id(spec_id))
			{
				guaranteed_revenue = guaranteed_harvest_bouns / 2;
			}
			n = n * ratio / 100 + guaranteed_revenue;

		}
		if (mode == 1)
		{
			if (building_id < 据点_末)
			{
				guaranteed_harvest = guaranteed_harvest_bouns;
			}
			else if (ch::is_valid_spec_id(spec_id))
			{
				guaranteed_harvest = guaranteed_harvest_bouns / 2;
			}
			n = n * ratio / 100 + guaranteed_harvest;
		}
		if (pk::enemies_around(building))
			n /= 2;

		return n;
	}

	// 探索的AI系数,由于AI探索失去一半的奖励,因此在这里补全.
	int incomes_difficulty_impact3(int n, bool is_player)
	{
		float ratio = 1.0;
		switch (pk::get_scenario().difficulty)
		{
			case 难易度_超级:
				if (is_player)
					ratio = 1.0f;
				else
					ratio = 2.0f;
				break;
			case 难易度_上级:
				if (is_player)
					ratio = 1.0f;
				else
					ratio = 1.5f;
				break;

			case 难易度_初级:
				if (is_player)
					ratio = 1.0f;
				else
					ratio = 1.2f;
				break;
		}
		return int(n * ratio);
	}

	bool func_49ed70(pk::point pos, int facility_id)
	{
		for (int i = 0; i < 方向_末; i++)
		{
			pk::point neighbor_pos = pk::get_neighbor_pos(pos, i);
			if (pk::is_valid_pos(neighbor_pos))
			{
				pk::building @building = pk::get_building(neighbor_pos);
				if (pk::is_alive(building) and building.facility == facility_id and building.completed)
					return true;
			}
		}
		return false;
	}

	int cal_spec_gold_income(int spec_id, int city_income)
	{
		int spec_person = ch::get_spec_person_id(spec_id);
		if (!pk::is_valid_person_id(spec_person))
			return 0;
		int building_id = ch::to_building_id(spec_id);
		pk::building @building = pk::get_building(building_id);

		int population_revenue = get_population_revenue(building_id);

		pk::person@ person = pk::get_person(spec_person);

		int gold_income = int((population_revenue * (0.8 + float(person.stat[武将能力_政治] * 0.005))));
		
		gold_income = incomes_global_impact(gold_income, building, 0);

		// 县城的辐射收入应该加在难度系数之后.避免重复对城市收入进行难度计算.
		//gold_income += int(city_income * 0.03);
		
		// 特技影响
		if (ch::has_skill(person, 特技_治县)) gold_income = int(gold_income * (100 + pk::core::skill_constant_value(特技_治县)) / 100);

		return gold_income;
	}

	int cal_spec_food_income(int spec_id, int city_income)
	{
		int spec_person = ch::get_spec_person_id(spec_id);
		if (!pk::is_valid_person_id(spec_person))
			return 0;
		int building_id = ch::to_building_id(spec_id);
		pk::building @building = pk::get_building(building_id);

		int population_harvest = get_population_harvest(building_id);

		pk::person@ person = pk::get_person(spec_person);

		int food_income = int((population_harvest * (0.8 + float(person.stat[武将能力_政治] * 0.005))));

		food_income = incomes_global_impact(food_income, building, 1);

		// 县城的辐射收入应该加在难度系数之后.避免重复对城市收入进行难度计算.
		//food_income += int(city_income * 0.03);

		// 特技影响
		if (ch::has_skill(person, 特技_治县)) food_income = int(food_income * (100 + pk::core::skill_constant_value(特技_治县)) / 100);

		return food_income;
	}

	pk::int_int cal_spec_pop_troops_income(int spec_id)
	{
		int spec_person = ch::get_spec_person_id(spec_id);
		if (!pk::is_valid_person_id(spec_person))
			return pk::int_int(0, 0);
		int building_id = ch::to_building_id(spec_id);
		pk::building @building = pk::get_building(building_id);
		auto spec_t = ch::get_spec_p(spec_id);
		pk::force @force = pk::get_force(building.get_force_id());

		//县城因为没有兵役政策,因此都按照90%人口增长被征为兵源计算.
		//因此征兵的AI加成和大城处理一样,都直接放在人口上
		float base_rate = 人口基础增长率;

		//县城由于人口少,因此使用了和城市人口不同的双曲线参数来提高人口增速
		float 人口修正 = (1 - log(spec_t.population / 10000) / 5 + 1.0f);

		// 将军的加成和难度的加成  大致上在1到1.5倍之间
		float 将军修正 = 1.0 + ((pk::get_person(spec_person).stat[武将能力_魅力] + pk::get_person(spec_person).stat[武将能力_政治]) / 2.0) * 0.005;

				// 拥立献帝的人口加成
		float 献帝_官职加成 = 0;
		if (pk::is_protecting_the_emperor(force))
			献帝_官职加成 = 0.0005;
		else
		{
		// 官职的人口加成,
			献帝_官职加成 = (10.0 - force.title) * 0.0005 * 0.1;
		}

		base_rate = 人口基础增长率 * 人口修正 * 将军修正 + 献帝_官职加成;

		// 育民只能增加基础的50%,而不是继续线性增加
		if (ch::has_skill(pk::get_person(spec_person), 特技_育民))
			base_rate += base_rate + (人口基础增长率 * pk::core::skill_constant_value(特技_育民) / 100); // 育民

		//兵临城下,每月损失2%的人口
		if (pk::enemies_around(building))
			base_rate -= 0.02;

		int pop_gain = pk::max(int(spec_t.population * base_rate),0);  //人口增长

		//pk::trace(pk::format("pop_gain {}", pop_gain));

		pop_gain = int(pop_gain * (building.is_player() ? 玩家征兵倍率 : 电脑征兵倍率) / 100.f);
		pop_gain = int(pop_gain * (building.is_player() ? 100 : inter::domestic_difficulty_impact()) / 100.f);

		if (city_tech::is_building_force_has_city(building, 39))
			pop_gain = int(pop_gain * 1.1f);

		int troops_gain = pk::min(spec_t.population / 300, int(pop_gain * 0.9));

		pop_gain = pk::max(int(pop_gain) - int(troops_gain), 0);

		return pk::int_int(pop_gain, troops_gain);
	}

	const int 初级电脑倍率 = 95;
	const int 上级电脑倍率 = 105;
	const int 超级电脑倍率 = 120;
	// 内政的倍率加成
	int domestic_difficulty_impact()
	{
		int 难度加成 = 0;
		switch (pk::get_scenario().difficulty)
		{
			case 难易度_初级:

				难度加成 = 初级电脑倍率;
				break;
			case 难易度_上级:

				难度加成 = 上级电脑倍率;
				break;

			case 难易度_超级:

				难度加成 = 超级电脑倍率;
				break;
		}
		return 难度加成;
	}

}